"""
后台系统视图函数
"""
import os
from io import BytesIO

from urllib.parse import quote

import xlwt

from django.db import connections
from django.http import HttpResponse, StreamingHttpResponse, JsonResponse

from backend.models import Emp, Dept

PAGE_SIZE = 10


def agent_bar_data(request):
    """生成图表数据"""
    names, totals = [], []
    # 可以通过django封装的connection和connections来获取数据库连接
    # 然后通过创建游标对象来发出原生SQL实现CRUD操作（性能更好）
    with connections['default'].cursor() as cursor:
        cursor.execute('select name, total from '
                       ' (select agentid, count(agentid) as total '
                       ' from tb_agent_estate group by agentid) t1 '
                       ' inner join tb_agent t2 on t1.agentid=t2.agentid')
        for row in cursor.fetchall():
            names.append(row[0])
            totals.append(row[1])
    # 将数据定制成JSON格式传递给浏览器
    # 如果data参数不是字典而是列表，还要加上safe=False参数
    # 如果字典或列中中有自定义对象，那么还需要通过encoder参数指定自定义对象如何做JSON序列化
    return JsonResponse({'names': names, 'totals': totals})


def download(request):
    """下载资源文件"""
    path = os.path.dirname(__file__)
    # 如果要动态生成PDF报表可以使用ReportLab三方库
    file_stream = open(f'{path}/resources/Git工作流程.pdf', 'rb')
    file_iter = iter(lambda: file_stream.read(4096), b'')
    resp = StreamingHttpResponse(file_iter, content_type='application/pdf')
    # resp['content-type'] = 'application/pdf'
    filename = quote('Git工作流程.pdf')
    # inline - 内联打开 / attachment - 附件下载
    resp['content-disposition'] = f'attachment; filename="{filename}"'
    return resp


def get_style(name, *, color=0, bold=False, italic=False):
    """按照指定的参数获得单元格样式"""
    style = xlwt.XFStyle()
    font = xlwt.Font()
    font.name = name
    font.colour_index = color
    font.bold = bold
    font.italic = italic
    style.font = font
    return style


def export_emp_excel(request, page):
    """导出Excel报表"""
    # 创建Excel工作簿
    workbook = xlwt.Workbook()
    # 向工作簿中添加工作表
    sheet = workbook.add_sheet('员工详细信息')
    # 设置表头
    titles = ('编号', '姓名', '职位', '主管', '工资', '部门')
    for col, title in enumerate(titles):
        sheet.write(0, col, title, get_style('HanziPenSC-W3', color=2, bold=True))
    # 可以通过only()或者defer()方法来进行SQL投影操作
    props = ('no', 'name', 'job', 'mgr', 'sal', 'dept')
    start, end = (page - 1) * PAGE_SIZE, page * PAGE_SIZE
    # 如果查询对象的同时还要查询它的关联对象 那么必须对自动生成的SQL语句进行优化
    # 否则将会引发1+N查询（也称为N+1查询，程序的性能会下降得非常明显而且数据库压力山大）
    # 如果有多对一关联，需要用连接查询加载关联对象那么可以用select_related()来加载
    # 如果有多对多关联，需要用连接查询加载关联对象那么可以用prefetch_related()来加载
    emps = Emp.objects.all().only(*props).select_related('dept').\
        select_related('mgr').order_by('-sal')[start:end]
    # 通过数据库获得的员工数据填写Excel表格
    for row, emp in enumerate(emps):
        for col, prop in enumerate(props):
            val = getattr(emp, prop, '')
            # 如果属性是关联的主管和部门对象则取它们的名字属性
            if isinstance(val, (Dept, Emp)):
                val = val.name
            sheet.write(row + 1, col, val)
    # 提取Excel表格的数据
    buffer = BytesIO()
    workbook.save(buffer)
    # 生成响应对象传输数据给浏览器
    resp = HttpResponse(buffer.getvalue(), content_type='application/msexcel')
    filename = quote('员工信息表.xls')
    resp['content-disposition'] = f'attachment; filename="{filename}"'
    return resp
